#ifndef __BLKTRACE_H__
#define __BLKTRACE_H__



#include "qe_def.h"
#include "qe_queue.h"



typedef struct
{
    qe_u32 chunk_size;
    qe_u32 chunks_per_block;
    qe_u32 start_block;
    qe_u32 end_block;
    qe_u32 num_cache_blocks;
} blktrace_blockio_config;

struct blocktrace_block_io;
typedef struct blocktrace_block_io blktrace_blockio;

typedef struct blocktrace_block_io
{
    blktrace_blockio_config config;
    qe_ret (*block_erase) (blktrace_blockio *bio, qe_u32 block_num);
    qe_ret (*chunk_write) (blktrace_blockio *bio, qe_u32 block_num, 
        qe_const_ptr data, qe_uint len);
    qe_ret (*chunk_read)  (blktrace_blockio *bio, qe_u32 block_num, 
        qe_ptr data, qe_uint len);
    qe_ret (*init)        (blktrace_blockio *bio);
    void *user;
} blktrace_blockio;

typedef struct 
{
    char start_mark[16];

    qe_u32 version;

    qe_u32 size;

    qe_u32 num_datas;

    qe_u32 max_datas;

    qe_u32 num_blocks;

    qe_u32 block_size;

    qe_u32 num_block_datas;

    qe_u32 next_free;

    qe_u32 serialize_count;

    qe_u32 is_full;
    qe_u32 is_active;

    qe_u32 data_start_mark;

    qe_u8 data[0];

    qe_u32 data_end_mark;

    char end_mark[16];
} blktrace_record;

typedef struct
{
    blktrace_blockio *bio;

    blktrace_record record;

    qe_ringq *buffer;

    qe_ringq *block_cache;

    qe_u32 data_size;
    qe_u32 meta_size;

    qe_u32 num_cache_blocks;
    qe_u32 num_cache_chunks;
    qe_u32 num_data_blocks;
    
    qe_bool is_initialized;

} blktrace;



blktrace *blktrace_new(qe_uint size);

qe_ret blktrace_set_blockio(blktrace *trace, blktrace_blockio *bio);
qe_ret blktrace_blockio_record(blktrace *trace, qe_const_ptr data, qe_uint num);



#endif /* __BLKTRACE_H__ */